/**
 * This file is part of decent-cpp.
 *
 * decent-cpp is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * decent-cpp is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with decent-cpp.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "crypto.h"
#include <sodium.h>
#include <iomanip>
#include <regex>
#include <sstream>
#include <stdexcept>

namespace dc {

uuid random_uuid() {
  uuid id;
  randombytes_buf(id.data(), id.size());
  return id;
}

std::string uuid_to_string(uuid id) {
  std::ostringstream out;
  out << std::hex;
  for (size_t i = 0; i < id.size(); i++) {
    out << std::setw(2) << std::setfill('0') << static_cast<int>(id[i]);
  }
  return out.str();
}

const std::regex uuid_regex("^[a-fA-F0-9]{32}$");

nonstd::optional<uuid> string_to_uuid(std::string string) {
  uuid id;
  if (!std::regex_match(string, uuid_regex)) {
    return nonstd::nullopt;
  }
  for (size_t i = 0; i < id.size(); i++) {
    id[i] = strtol(string.substr(i * 2, 2).c_str(), nullptr, 16);
  }
  return id;
}

std::string pwd_hash(std::string pwd) {
  char hashed[crypto_pwhash_STRBYTES];
  if (crypto_pwhash_str(hashed, pwd.c_str(), pwd.size(),
                        crypto_pwhash_OPSLIMIT_MODERATE,
                        crypto_pwhash_MEMLIMIT_MODERATE) != 0) {
    throw std::runtime_error("Libsodium out of memory");
  }
  return std::string(hashed);
}

bool pwd_verify(std::string pwd, std::string hash) {
  return crypto_pwhash_str_verify(hash.c_str(), pwd.c_str(), pwd.size()) == 0;
}

}  // namespace dc